Skip to content

feat: Rust fd5 audit trail with identity and chain verification#173

Open
gerchowl wants to merge 2 commits intofeature/123-fd5-rust-cratefrom
feature/167-rust-audit-trail
Open

feat: Rust fd5 audit trail with identity and chain verification#173
gerchowl wants to merge 2 commits intofeature/123-fd5-rust-cratefrom
feature/167-rust-audit-trail

Conversation

@gerchowl
Copy link
Contributor

@gerchowl gerchowl commented Mar 2, 2026

Summary

  • Add audit.rs: tamper-evident audit log stored as JSON in _fd5_audit_log HDF5 attribute, with read_audit_log / append_audit_entry functions and cross-language-compatible JSON format matching the Python spec
  • Add identity.rs: user identity loaded from ~/.fd5/identity.toml (TOML format), with anonymous fallback and Author conversion for audit entries
  • Extend edit.rs: EditPlan now carries message and author fields; apply() automatically creates an audit entry with parent_hash, timestamp, author, message, and change details before recomputing content_hash
  • Add verify_chain to verify.rs: reconstructs intermediate file states by reversing recorded attribute edits to verify each parent_hash link in the audit chain, detecting broken chains with precise index/expected/actual diagnostics

Implementation details

  • Audit log attribute (_fd5_audit_log) is NOT in EXCLUDED_ATTRS, so it participates in the Merkle tree and any tampering is detected by verify
  • Chain verification works by copying the file to a temp location and iteratively undoing changes in reverse order, recomputing the Merkle hash at each step
  • Developed in RED-GREEN TDD: 15 failing tests committed first, then implementations to make all 19 tests pass (15 new + 4 existing)

Test plan

  • cargo test -p fd5 --lib — all 19 tests pass
  • test_audit_entry_serde — JSON roundtrip with correct field names (type not author_type)
  • test_read_empty_log — empty file returns Ok(vec![])
  • test_write_read_roundtrip — append + read returns identical entry
  • test_append_preserves_existing — two appends yield both entries
  • test_malformed_json_error — bad JSON produces clear error
  • test_anonymous_default — anonymous identity has expected fields
  • test_save_load_roundtrip — TOML save + load returns identical identity
  • test_missing_file_returns_anonymous — missing TOML falls back to anonymous
  • test_to_author_conversion — Identity to Author field mapping correct
  • test_edit_creates_audit_entry — edit produces audit log with 1 entry
  • test_edit_preserves_existing_log — two edits produce 2-entry log
  • test_audit_entry_has_correct_parent_hash — parent_hash matches pre-edit content_hash
  • test_content_hash_covers_audit_log — tampering audit log breaks Merkle verify
  • test_no_log_returns_nolog — file without audit log returns ChainStatus::NoLog
  • test_single_entry_valid — one edit validates as Valid(1)
  • test_valid_chain — two edits validate as Valid(2)
  • test_broken_chain_detected — fake entry with wrong parent_hash detected at correct index

Closes #167, closes #168, closes #169, closes #170

🤖 Generated with Claude Code

gerchowl and others added 2 commits March 2, 2026 10:42
…d chain verification

Add test skeletons with todo!() stubs for:
- audit.rs: serde roundtrip, read/write/append, malformed JSON
- identity.rs: anonymous default, save/load roundtrip, to_author
- edit.rs: audit entry creation, preservation, parent_hash, tamper detection
- verify.rs: chain verification (valid, no log, broken chain, single entry)

Refs: #167, #168, #169, #170

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…g, and chain verification

All 19 tests pass (15 new + 4 existing):

audit.rs: read/write audit log as JSON in _fd5_audit_log HDF5 attribute
- read_audit_log returns empty vec when attr missing
- append_audit_entry preserves existing entries
- Malformed JSON returns clear Fd5Error::Json

identity.rs: load/save identity from TOML files
- anonymous() default when no config exists
- load_from falls back to anonymous for missing files
- to_author converts Identity -> Author for audit entries

edit.rs: EditPlan::apply now creates audit entries automatically
- Records parent_hash, timestamp, author, message, and changes
- Audit log participates in Merkle tree (tamper-evident)
- content_hash recomputed after audit entry is appended

verify.rs: verify_chain reconstructs intermediate states
- Reverses attribute edits to verify each parent_hash link
- Detects broken chains with index, expected, and actual hashes
- Thread-safe temp file handling with atomic counter

Refs: #167, #168, #169, #170

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant